#include "StdAfx.h"
#include "DBMySql.h"
namespace DDM {

DB_MySql::DB_MySql(void)
{
	conn = mysql_init(NULL);
}

DB_MySql::~DB_MySql(void)
{
	mysql_close(conn);
}

int DB_MySql::connect(const char *host, const char *user, const char *passwd, const char *db)
{
	conn = mysql_init(conn);
	if (!mysql_real_connect(conn, host, user, passwd, db, 0, NULL, 0))
		return -DBERR_CONN;

	char rec = 1;
	if (mysql_options(conn, MYSQL_OPT_RECONNECT, &rec) < 0)
		return -DBERR_CONN;

	isConnected = true;
	return DBERR_NOERR;
}
bool DB_MySql::IsConnected()
{
	if (mysql_ping(conn) < 0)
		isConnected = false;
	return isConnected;
}

void DB_MySql::close()
{
	if (!isConnected)
		return;

	mysql_close(conn);
	conn = NULL;
}

int DB_MySql::execute(const char *sql)
{
    printk("execute: %s\n", sql);
	int ret = mysql_query(conn, sql);
    printk("execute: %s, end\n", sql);
	return ret == 0 ? 0 : -1;
}

int DB_MySql::real_execute(const char *sql, vector<DBCol *> *pcols)
{
	int err_code = DBERR_NOERR;
	MYSQL_STMT *stmt;

    printk("real_execute: %s\n", sql);
	stmt = mysql_stmt_init(conn);
	if (!stmt)
		return -DBERR_CONN;

	if (mysql_stmt_prepare(stmt, sql, strlen(sql)) < 0) {
		err_code = -DBERR_STMT;
		goto out;
	}

	int param_count = mysql_stmt_param_count(stmt);
	if (param_count != pcols->size()) {
		err_code = -DBERR_SQL;
		goto out;
	}

	MYSQL_BIND *bind = new MYSQL_BIND[pcols->size()];
	for (int i = 0; i < param_count; i++) {
		memset(&bind[i], 0, sizeof(MYSQL_BIND));
		DBCol *pcol = pcols->at(i);

		bind[i].buffer_type = MYSQL_TYPE_BLOB;
		bind[i].buffer = pcol->data;
		bind[i].buffer_length = pcol->len;
		bind[i].length = &pcol->len;
	}

	if (mysql_stmt_bind_param(stmt, bind)) {
		err_code = -DBERR_STMT;
		goto out;
	}

	if (mysql_stmt_execute(stmt)) {
		err_code = -DBERR_STMT;
		goto out;
	}

	my_ulonglong affected_rows = mysql_stmt_affected_rows(stmt);
	if (affected_rows != 1) {
		err_code = -DBERR_STMT;
		goto out;
	}

out:
	delete[] bind;
	mysql_stmt_close(stmt);
    printk("real_execute: %s, end\n", sql);
	return err_code;
}

int DB_MySql::execute_with_result(const char *sql, vector<DBRow *> *prows)
{
	if (execute(sql) < 0) return -DBERR_CONN;

	MYSQL_RES *result = mysql_store_result(conn);
	if (!result) return -DBERR_CONN;

	MYSQL_ROW row;
	my_ulonglong num_rows = mysql_num_rows(result);
	unsigned int num_cols = mysql_num_fields(result);
	MYSQL_FIELD *cols_info = mysql_fetch_fields(result);
	while (row = mysql_fetch_row(result)) {
		unsigned long *lengths = mysql_fetch_lengths(result);

		DBRow *prow = new DBRow();
		for (my_ulonglong i = 0; i < num_cols; i++) {
			DBCol *pcol = new DBCol();
			pcol->len = lengths[i];
			if (cols_info[i].type == MYSQL_TYPE_LONG) {
				pcol->data = (void *)atoi(row[i]);
			} else {
				pcol->data = new char[pcol->len];
				memcpy(pcol->data, row[i], pcol->len);
				pcol->alloced = 1;
			}
			prow->cols.push_back(pcol);
		}
		prows->push_back(prow);
	}
	mysql_free_result(result);
	return(int)num_rows;
}

const char* DB_MySql::db_error() const
{
	return mysql_error(conn);
}
}
